#! /usr/bin/env node
/*eslint-disable*/
// https://gitee.com/jipengju/dashboard/projects
const program = require(`commander`) // 命令行中参数的处理
const inquirer = require(`inquirer`) // 命令行中的select 选择器
const downloadRepo = require(`download-git-repo`) // 仓库下载
const ora = require(`ora`) // Loading
const figlet = require(`figlet`) // 生成好看的标识颜色
const Printer = require('@darkobits/lolcatjs') // 生成随机颜色
const chalk = require(`chalk`)//给提示文案着色 *注:5版本是esm，如果在ts中或者构建工具中使用，目前建议使用4版本
const myUtil = require(`./utils/myUtil`)  // 私有工具集
const clear = require('clear') // 清屏

// 常量
const packageJson = require(`./package.json`)
const cliName = packageJson.projectName // cli名称
const repoCurrentVersion = packageJson.version // 当前的版本
const repolatestVersionObj = myUtil.checkUpdateVersion(packageJson.name, repoCurrentVersion, packageJson.repository.npmUrl) // 获取最新的版本
const repoLastVersion = repolatestVersionObj.lastVersion // 上一次版本
const repolatestVersion = repolatestVersionObj.latest // 最新的版本
const repoNodeVersion = packageJson.engines.node // 获取工程依赖node版本
const nodeVersion = process.version // 系统node版本
const Log = console.log // 日志

// Log(repolatestVersionObj)

// 全局变量
let Loading = null // 创建加载器

// 系统色彩变量
const repoColor = {
    warning: `#f40` // 警告
}
// cli 图标
const repoLogo = figlet.textSync(`${cliName}`, {
    font: `epic`,
    horizontalLayout: `Smush (U)`,
    verticalLayout: `Smush (U)`
})


// 检测node版本
if (!myUtil.checkNodeVersion(nodeVersion, repoNodeVersion))
    return


// CLI对象
const myCli = {
    /*
    * 执行回调
    * projectName 项目名
    * option 对应上面的指令选项
    * */

    // 检测是否存在重名项目
    checkIsHasProject(projectName) {
        return new Promise((resolve, reject) => {
            if (myUtil.hasFileName(projectName)) {
                inquirer.prompt([
                    {
                        type: 'list',
                        name: 'DeleteAndUpdate',
                        message: `检测到本地已存在名字为${projectName}的工程目录/文件，是否需要自动删除并创建？`,
                        choices: [
                            {
                                name: `自动删除并创建${chalk.hex(repoColor.warning)(`[该项会自动删除重名目录，请谨慎操作]`)}`, value: 1
                            },
                            {
                                name: '手动删除',
                                value: 0
                            }
                        ]
                    }
                ]).then((answer) => {
                    if (!answer.DeleteAndUpdate) {
                        resolve(answer.DeleteAndUpdate)
                        return
                    }
                    myUtil.deleteDir(ora, projectName).then(t => {
                        resolve(answer.DeleteAndUpdate)
                    })
                })
            } else {
                resolve(true)
            }
        })
    },
    // 拉取项目
    cloneProject(url, name) {
        Loading = ora({
            text: chalk.greenBright(`正在拉取脚手架...`)
        }).start() // 开始状态 => 加载状态
        downloadRepo(
            `direct:${url}`,
            name,
            { clone: true },
            err => {
                if (err) return Loading.warn(chalk.redBright(`=====| 脚手架已存在或仓库资源错误 |=====`)) // 加载状态 => 成功状态
                Loading.succeed(chalk.greenBright(`=========| 脚手架创建成功 |=========`)) // 加载状态 => 成功状态
                Loading.succeed(chalk.greenBright(`------------------------------------`)) // 加载状态 => 成功状态
                Loading.succeed(chalk.greenBright(`------------------------------------`)) // 加载状态 => 成功状态
                Loading.succeed(chalk.greenBright(`------------------------------------`)) // 加载状态 => 成功状态
                Loading.succeed(chalk.greenBright(`============| 运行指南 |============`)) // 加载状态 => 成功状态
                Loading.succeed(chalk.greenBright(`====| ${Printer.fromString(`npm install`)}   [拉取依赖] |====`)) // 加载状态 => 成功状态
                Loading.succeed(chalk.greenBright(`====| ${Printer.fromString(`npm run serve`)} [项目启动] |====`)) // 加载状态 => 成功状态
            }
        )
    },

    // cli 初始化
    _init(projectName, option) {
        clear()
        // welcome
        Log(chalk.blueBright(repoLogo))
        Log(chalk.blueBright(`Hello, Welcome to ${cliName}!`))

        // cli init
        const projectType = Object.keys(option).length ? Object.keys(option)[0].toLowerCase() : null

        // 类型判断
        if (projectType) { // 默认指令
            Log(chalk.green(`去生成一个web-${projectType}...`))
            myCli.checkIsHasProject(projectName).then(isHas => {
                if (!isHas) {
                    Log(chalk.hex(repoColor.warning)(`请自行删除本地的${projectName}工程目录/文件！`))
                    return
                }
                myCli.cloneProject(packageJson.repository[`${projectType}Url`], projectName)
            })
        } else { // 自定义
            Log(chalk.hex(repoColor.warning)(`你好，欢迎使用${cliName}！`))

            //筛选问题
            const questions = [
                {
                    type: 'input',
                    name: 'customProjectName',
                    message: '请输入项目名称:',
                    validate: function (val) {
                        if (val.match(/^[A-Za-z0-9\( \)\-\#]+$/g)) {
                            return true
                        }
                        return '请输入规范的项目名称'
                    },
                    when: (answer) => {
                        if (!answer.customProjectName) {
                            return true
                        }
                        return false
                    }
                },
                {
                    type: `list`,
                    name: `framework`,
                    message: `请选择需要的脚手架:`,
                    default: `pc-|cut|-${packageJson.repository.pcUrl}`,
                    choices: [
                        {
                            name: 'pc端脚手架',
                            value: `pc-|cut|-${packageJson.repository.pcUrl}`
                        }, {
                            name: '移动端脚手架',
                            value: `h5-|cut|-${packageJson.repository.h5Url}`
                        }
                    ],
                    when: (answer) => {
                        if (answer.customProjectName) {
                            Log(chalk.red(`\n\nVue CLI v4.5.13`))
                            if (repolatestVersion > repoCurrentVersion) {
                                Log(`
┌───────────────────────────────────────────┐
│                                           │
│         Hello, I'm Penn Ji.               │
│       the author of Penn-CLI.             │
│         ${Printer.fromString(`Welcome to `)}${Printer.fromString(`use it.`)}                │
│                                           │
│     Your current version is ${chalk.red(`${repoCurrentVersion}`)}         │
│   New version available ${chalk.hex(repoColor.warning)(`${repoLastVersion}`)} → ${chalk.hex(repoColor.warning)(`${repolatestVersion}`)}     │
│     Run ${chalk.hex(repoColor.warning)(`npm i -g penn-cli`)} to update!      │
│                                           │
└───────────────────────────────────────────┘
                        `)
                            } else {
                                Log(`
┌───────────────────────────────────────────┐
│                                           │
│         Hello, I'm Penn Ji.               │
│       the author of Penn-CLI.             │
│         ${Printer.fromString(`Welcome to `)}${Printer.fromString(`use it.`)}                │
│                                           │
│     Your current version is ${chalk.red(`${repoCurrentVersion}`)}         │
│       You're the ${chalk.greenBright(`latest version`)}!          │
│                                           │
└───────────────────────────────────────────┘
                        `)
                            }
                        }
                        return true
                    }
                }
            ]
            // 自定义默认项
            const answers = {
                customProjectName: projectName
            }
            // Log(`answers==>${JSON.stringify(answers)}`)
            inquirer.prompt(questions, answers)
                .then((answer) => {
                    if (answer.framework) {
                        const frameworkArr = answer.framework.split(`-|cut|-`)
                        answer.frameworkObj = {
                            name: frameworkArr[0],
                            url: frameworkArr[1]
                        }
                        Log(JSON.stringify(answer))
                        Log(chalk.green(`去生成一个web-${answer.frameworkObj.name}...`))
                        const _projectName = answer.customProjectName
                        myCli.checkIsHasProject(_projectName).then(isHas => {
                            if (!isHas) {
                                Log(chalk.hex(repoColor.warning)(`请自行删除本地的${_projectName}工程目录/文件！`))
                                return
                            }
                            myCli.cloneProject(packageJson.repository[`${answer.frameworkObj.name}Url`], _projectName)
                        })
                    } else {
                        return
                    }
                })
        }
    },

    // 构建
    _build() {
        // 开始构建
        program
            .version(
                // 彩虹色logo
                Printer.fromString(
                    `   \n      Penn-CLI v${repoCurrentVersion}\n   ${repoLogo}\n    Hello, Welcome to ${cliName}!`
                )
            ) // 获取版本 以package.json 版本信息为准
            .description(`欢迎使用${cliName}脚手架~`) // 脚手架描述
            .option(`-F, --framework`, `指定创建的脚手架，目前支持web-pc和web-h5`) // 指定构建的脚手架
            .configureOutput({
                // 此处使输出变得容易区分
                writeOut: (str) => process.stdout.write(`[OUT] ${str}`),
                writeErr: (str) => process.stdout.write(`[ERR] ${str}`),
                // 将错误高亮显示
                // outputError: (str, write) => write(chalk.hex(repoColor.warning)(str))
                outputError: (str, write) => write(chalk.red(str))
            })
            .command(`create [projectName]`)
            .description(`创建脚手架`)
            .option(`-pc`, `生成一个用于web-pc的项目脚手架`)
            .option(`-h5`, `生成一个用于web-h5的项目脚手架`)
            .action((projectName, option, command) => (myCli._init(projectName, option)))

        program.parse(process.argv) // 解析指令
    }
}

myCli._build()

